package annotation;

import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 自定义注解，名字为Entity
 * 注意：我们自己写的所有注解都默认继承Annotation接口
 * @Target用于定义，你字节写注解可以描述哪些对象
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Entity {
    String value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@interface ID{
    int value();
}
@Target(ElementType.PARAMETER)
@interface Validate{}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
@interface Log{}

/**
 * 使用注解描述类
 */
@Log
@Entity("tb_user")
class  User{
    @ID(100)
    private Integer id;

    private void setId(@Validate Integer id){
        this.id = id;
    }
    @Log
    public Integer getId(){
        return id;
    }
}

public class AnnotationDemo01 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //案例1：获取User类上的Entity注解，然后获取注解中的value属性值
        //1.获取类的字节码对象
        Class<User> userClass = User.class;
        //2.判断类上是否有制定注解
        boolean flag = userClass.isAnnotationPresent(Entity.class);
        System.out.println(flag); //true
        //3.获取类上的注解
        Entity entity = userClass.getAnnotation(Entity.class);
        System.out.println(entity instanceof Annotation); //true
        System.out.println(entity.value());

        //案例2：将@ID注解中的100，赋值给@ID注解描述的id属性
        //1.获取User类中的ID属性
        Field fis = userClass.getDeclaredField("id");
        //2.获取属性上面的ID注解
        boolean isID = fis.isAnnotationPresent(ID.class);
        if (!flag)return;
        ID id = fis.getAnnotation(ID.class);
        //3.调用注解对象的value方法获取注解中的值
        int idValue = id.value();
        //4.为ID注解描述的属性赋值
        fis.setAccessible(true);
        User user = new User();
        fis.set(user,idValue); //为user对象的id属性赋值
        System.out.println(fis.get(user));

        //案例3：获取类中的所有方法，加入方法上有@Log注解，则输出一句话，这个方法执行要记录日志
        Method[] methods = userClass.getDeclaredMethods();
        for (Method method : methods) {
            boolean isLog = method.isAnnotationPresent(Log.class);
            if (isLog){
                System.out.println("执行了"+method.getName()+"方法要记录日志");
            }
        }
    }
}
